package com.wangshuqi.jdbc.preparedStatement;

import com.wangshuqi.jdbc.bean.Customer;
import com.wangshuqi.jdbc.bean.Order;
import com.wangshuqi.jdbc.util.JDBCUtil;
import jdk.nashorn.internal.scripts.JD;
import org.junit.Test;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.List;

/**
 * 使用preparedStatement进行查询操作
 *
 * @author codewsq
 * @date 2021/8/21 0021 17:07
 */
public class PreparedStatementQueryTest {

    /*
     * jdbc查询数据库单条数据（完整流程）
     * 1. 查询customers表的某一条数据
     * */
    @Test
    public void test1() {
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        try {
            // 1.获取数据库连接
            connection = JDBCUtil.getConnection();
            // 2.编写sql语句
            String sql = "select id,name,email,birth from customers where id = ?";
            // 3.预编译sql
            ps = connection.prepareStatement(sql);
            ps.setObject(1, 12);
            // 4.执行查询并返回结果集
            resultSet = ps.executeQuery();
            // 5.判断结果集是否有数据，有数据取出数据
            if (resultSet.next()) {
                int id = resultSet.getInt(1);
                String name = resultSet.getString(2);
                String email = resultSet.getString(3);
                Date birth = resultSet.getDate(4);

                Customer customer = new Customer(id, name, email, birth);
                System.out.println(customer);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 6.关闭连接
            JDBCUtil.closeConnection(connection, ps, resultSet);
        }
    }

    /*
     * 2. 查询customers表的某一条数据
     *    当不确定查询结果集返回列时，该怎么做？
     *      2.1 获取数据集列的个数
     *      2.2 通过反射获取列对应的javabean属性名称，并赋值
     * */
    @Test
    public void test2() {
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        try {
            // 1.获取数据库连接
            connection = JDBCUtil.getConnection();
            // 2.编写sql语句
            String sql = "select id,name,email,birth from customers where id = ?";
            // 3.预编译sql
            ps = connection.prepareStatement(sql);
            ps.setObject(1, 12);
            // 4.执行查询并返回结果集
            resultSet = ps.executeQuery();
            ResultSetMetaData metaData = resultSet.getMetaData(); // 通过ResultSetMetaData的对象获取列的类型及属性信息
            int columnCount = metaData.getColumnCount(); // 获取列的个数
            // 5.判断结果集是否有数据，有数据取出数据
            if (resultSet.next()) {
                Customer customer = new Customer();
                for (int i = 0; i < columnCount; i++) {
                    String columnName = metaData.getColumnName(i + 1); // 获取列的名称
                    Field field = Customer.class.getDeclaredField(columnName); // 通过反射获取javabean的属性
                    field.setAccessible(true); // 开启操作权限
                    field.set(customer, resultSet.getObject(i + 1)); // 给属性赋值
                }
                System.out.println(customer);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 6.关闭连接
            JDBCUtil.closeConnection(connection, ps, resultSet);
        }
    }

    /*
     * 3.查询order表，表别名和javabean属性对应
     *  问题：数据库表的列名和javabean中的属性名不同，怎么做
     *       3.1 查询时，给要查询的列取别名，列的别名和javabean的属性名相同
     *       3.2 通过getColumnLabel(int column) 方法获取列别名，也就是查询到的结果集的列名
     * */
    @Test
    public void test3() {
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        try {
            // 1.获取数据库连接
            connection = JDBCUtil.getConnection();
            // 2.编写sql语句
            String sql = "select order_id orderId,order_name orderName,order_date orderDate from `order` where order_name = ?";
            // 3.预编译sql
            ps = connection.prepareStatement(sql);
            ps.setObject(1, "BB");
            // 4.执行查询并返回结果集
            resultSet = ps.executeQuery();
            ResultSetMetaData metaData = resultSet.getMetaData(); // 通过ResultSetMetaData的对象获取列的类型及属性信息
            int columnCount = metaData.getColumnCount(); // 获取列的个数
            // 5.判断结果集是否有数据，有数据取出数据
            if (resultSet.next()) {
                Order order = new Order();
                for (int i = 0; i < columnCount; i++) {
//                    String columnName = metaData.getColumnName(i + 1); // 获取列的名称
                    String columnLabel = metaData.getColumnLabel(i + 1); // 获取列的别名 （推荐使用，之后就用该方法获取结果集列名）
                    Field field = Order.class.getDeclaredField(columnLabel); // 通过反射获取javabean的属性
                    field.setAccessible(true); // 开启操作权限
                    field.set(order, resultSet.getObject(i + 1)); // 给属性赋值
                }
                System.out.println(order);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 6.关闭连接
            JDBCUtil.closeConnection(connection, ps, resultSet);
        }
    }

    // 使用封装的查询方法查询数据库数据
    @Test
    public void test4() {
        // 根据id查询customers表数据
        String sql = "select id,name,email,birth from customers where id = ?";
        Integer id = 18;
        Customer customer = JDBCUtil.selectOne(Customer.class, sql, id);
        System.out.println(customer);

        // 根据name查询order表
        sql = "select order_id orderId,order_name orderName,order_date orderDate from `order` where order_name = ?";
        Order order = JDBCUtil.selectOne(Order.class, sql, "AA");
        System.out.println(order);
    }

    // 使用封装的查询方法查询多条数据库数据
    @Test
    public void test5() {
        // 查询小于指定id的所有客户信息
        String sql = "select id,name,email,birth from customers where id < ?";
        Integer id = 18;
        List<Customer> customers = JDBCUtil.selectList(Customer.class, sql, id);
        customers.forEach(System.out::println);

        System.out.println();
        // 根据指定名称的order信息
        sql = "select order_id orderId,order_name orderName,order_date orderDate from `order` where order_name in (?,?)";
        List<Order> orders = JDBCUtil.selectList(Order.class, sql, "AA", "GG");
        orders.forEach(System.out::println);
    }
}
